package org.dromara.llm.util;

public class AudioVoiceDetection {

    /**
     * 判断 PCM 音频数据中是否有声音
     * @param pcmData PCM 音频数据字节数组
     * @param sampleRate 采样率
     * @param bitsPerSample 每个样本的位数（例如 16 位）
     * @param channels 声道数（1 为单声道，2 为立体声）
     * @param threshold 声音阈值（范围：0.0 到 1.0）
     * @return 如果检测到声音返回 true，否则返回 false
     */
    public static boolean hasVoice(byte[] pcmData, int sampleRate, int bitsPerSample, int channels, double threshold) {
        // 确保阈值在有效范围内
        threshold = Math.max(0.0, Math.min(1.0, threshold));

        // 计算均方根（RMS）值，它是音频能量的指标
        double rms = calculateRMS(pcmData, bitsPerSample, channels);

        // 将 RMS 值转换为 0 到 1 之间的相对值
        double relativeRMS = rms / Short.MAX_VALUE;

        // 比较相对 RMS 值与阈值
        return relativeRMS > threshold;
    }

    /**
     * 计算 PCM 数据的均方根（RMS）值
     */
    private static double calculateRMS(byte[] pcmData, int bitsPerSample, int channels) {
        long sum = 0;
        int sampleCount = 0;

        // 根据每个样本的位数处理 PCM 数据
        if (bitsPerSample == 16) {
            // 16位 PCM 数据（每个样本占2个字节）
            for (int i = 0; i < pcmData.length; i += 2 * channels) {
                for (int ch = 0; ch < channels; ch++) {
                    if (i + 2 * ch < pcmData.length) {
                        // 将两个字节转换为一个 short（16位整数）
                        short sample = (short) ((pcmData[i + 2 * ch + 1] << 8) | (pcmData[i + 2 * ch] & 0xFF));
                        sum += (long) sample * sample;
                        sampleCount++;
                    }
                }
            }
        } else if (bitsPerSample == 8) {
            // 8位 PCM 数据（每个样本占1个字节）
            for (int i = 0; i < pcmData.length; i += channels) {
                for (int ch = 0; ch < channels; ch++) {
                    if (i + ch < pcmData.length) {
                        // 将字节转换为整数（需要考虑有符号性）
                        int sample = pcmData[i + ch];
                        sum += (long) sample * sample;
                        sampleCount++;
                    }
                }
            }
        } else {
            throw new IllegalArgumentException("不支持的位深度: " + bitsPerSample + " 位");
        }

        if (sampleCount == 0) {
            return 0;
        }

        // 计算均方根
        double meanSquare = (double) sum / sampleCount;
        return Math.sqrt(meanSquare);
    }

    // 示例用法
    public static void main(String[] args) {
        // 这里只是示例，实际使用时需要替换为真实的 PCM 数据
        byte[] pcmData = new byte[1024]; // 假设这是从音频流中读取的 PCM 数据

        int sampleRate = 16000; // 采样率 44.1kHz
        int bitsPerSample = 16; // 16位深度
        int channels = 1;       // 单声道
        double threshold = 0.01; // 阈值，可根据实际环境调整

        boolean hasVoice = hasVoice(pcmData, sampleRate, bitsPerSample, channels, threshold);
        System.out.println("检测结果: " + (hasVoice ? "有声音" : "无声音"));
    }
}
